<?php
/**
 *
 * @author Mr.UBKey
 * @package XPHP
 * @version Beta
 * @copyright XWEB
 */

require_once 'XPHP/String.php';
require_once 'XPHP/Array.php';

class XPHP_Router
{
	/**
	 * Mảng lưu trữ  request uri
	 * @var array
	 */
	protected $_requestUri;
    
    /**
     * Danh sách các area và đường dẫn đến area
     * @var array
     */
    protected $_areas;
    
    /**
     * Tên area
     * @var string
     */
    protected $_area;
    /**
     * Prefix của area
     * @var string
     */
    protected $_areaKey;
    
    /**
     * Tên controller
     * @var string
     */
    protected $_controller;
    
    /**
     * Prefix của controller
     * @var string
     */
    protected $_controllerKey;
    
    /**
     * Tên action
     * @var string
     */
    protected $_action;
    
    /**
     * Prefix của action
     * @var string
     */
    protected $_actionKey;

    /**
     * Prefix của action post
     * @var string
     */
    protected $_actionPOSTKey;
    
    /**
     * Prefix của action get
     * @var string
     */
    protected $_actionGETKey;
    
    /**
     * Prefix của action ajax
     * @var string
     */
    protected $_actionAJAXKey;
    
    /**
     * Tên thư mục chứa area
     * @var string 
     */
    protected $_areaDir;
    
    /**
     * Tên thư mục chứa controller
     * @var string 
     */
    protected $_controllerDir;
    
    /**
     * Tên thư mục chứa ứng dụng
     * @var string 
     */
    protected $_applicationDir;
    
    /**
     * Tham số truyền vào từ QueryString
     * @var array 
     */
    protected $_args = array();
    
	/**
	 * Khởi tạo các giá trị cho Router
	 */
	public function __construct()
	{
		/*
		 * Khởi tạo các giá trị mặc định 
		 */
		$this->_areaKey = "";
		$this->_actionKey = "Action";
		$this->_actionAJAXKey = "AJAX";
		$this->_actionPOSTKey = "POST";
		$this->_actionGETKey = "GET";
		$this->_controllerKey = "Controller";
		
		$this->_applicationDir = "application";
		$this->_areaDir = "areas";
		$this->_controllerDir = "controllers";
		
	}
	
	/**
	 * Gán một thể hiện của Router
	 * @param $router
	 * @return XPHP_Router
	 */
	public static function setInstance($router)
	{
		if(get_class($router) == "XPHP_Router")
			return $router;
		else if(is_array($router))
		{
			if(isset($router['action']))
				$this->setAction($router['action']);
			if(isset($router['controller']))
				$this->setController($router['controller']);
			if(isset($router['area']))
				$this->setArea($router['area']);
			if(isset($router['args']))
				$this->setArgs($router['args']);
			return $this;
		}
	}
	
    /**
     * Lấy ra toàn bộ areas có trong thư mục areas và đường dẫn
     * @param void
     * @return array $areaName => $areaPath
     */
    
    public function getAreas()
    {
    	require_once 'XPHP/Directory.php';
    	
    	$this->_areas = XPHP_Directory::getSubDirectories($this->_areaDir);

    	return $this->_areas;
    }
    
    /**
     * Kiểm tra, phân tích request uri lấy ra Area, Controller, Action, Param (Thông tin router)
     * @param void
     * @return array Trả về mảng lưu trữ thông tin của router
     */
    
    public function analysisRequestUri()
    {
    	//Lấy toàn bộ area và đường dẫn
    	$this->getAreas();
    	//Lấy ra request uri
    	$params = $this->getRequestUri();

    	foreach ($params as $param)
    	{
    		if($this->isArea($param) && empty($this->_area))
    		{
    			$this->setArea(XPHP_String::secure($param)); //area
    			array_shift($params);
    			continue;
    		}
    		if($this->isController($param) && empty($this->_controller))
    		{
    			$this->setController(XPHP_String::secure($param)); //controller
    			array_shift($params);
    			continue;	
    		}
    		if($this->isAction($param) && empty($this->_action))
    		{
    			$this->setAction(XPHP_String::secure($param)); //action
    			array_shift($params);
    			break;	
    		}
    	}
    	
    	//args
    	$this->setArgs(XPHP_Array::secure($params), true);
    	
    	//Default controller and action
    	if(empty($this->_controller))
    		$this->setController("Index");
    	if(empty($this->_action))
    		$this->setAction("index");
    }
    
    /**
     * Kiểm tra xem tham số truyền vào có phải area hay không ?
     * @param string Chuỗi cần kiểm tra
     * @return boolean
     */
    public function isArea($part)
    {
    	if(empty($this->_requestUri))
    		$this->getRequestUri();
    	
    	return isset($this->_areas[$part]);
    }
    
    /**
     * Kiểm tra xem tham số truyền vào có phải controller hay không ?
     * @param string Chuỗi cần kiểm tra
     * @return boolean
     */
    public function isController($part)
    {
    	//Nếu có area
    	if(!empty($this->_area))
    		$cfile = $this->_areas[$this->_area] . DIRECTORY_SEPARATOR . $this->_controllerDir 
    											 . DIRECTORY_SEPARATOR . $this->_area . "_" . $part . $this->_controllerKey . '.php';	
    	//Nếu không có area 
    	else 
    		$cfile = $this->_applicationDir . DIRECTORY_SEPARATOR . $this->_controllerDir 
    									    . DIRECTORY_SEPARATOR . $part . $this->_controllerKey . '.php';		
    	return is_file($cfile);
    }

    /**
     * Kiểm tra xem tham số truyền vào có phải action hay không ?
     * @param string Chuỗi cần kiểm tra
     * @return boolean
     */
    public function isAction($part)
    {
    	//Nếu có area
    	if(!empty($this->_area) && !empty($this->_controller))
    		$class = $this->_area . $this->_areaKey . '_' . $this->_controller . $this->_controllerKey;
    	else if(!empty($this->_controller))
    		$class = $this->_controller . $this->_controllerKey;
    	else 
    		return false;	
    	
    	$isAction = false;
    	//Kiểm tra xem có một trong những thể hiện của action hay không ?
    	if(method_exists($class,$part . $this->_actionKey))
    		$isAction = true;
    	else if(method_exists($class,$part . $this->_actionAJAXKey))
    		$isAction = true;
    	else if(method_exists($class,$part . $this->_actionPOSTKey))
    		$isAction = true;
    	else if(method_exists($class,$part . $this->_actionGETKey))
    		$isAction = true;
    		
    	return $isAction;
    }
    
    
    /**
     * Lấy ra request uri lưu lại dưới dạng mảng
     * @param void
     * @return array
     */
    public function getRequestUri()
    {
    	require_once 'XPHP/Uri.php';
    	
    	$uri = new XPHP_Uri();
    	$this->_requestUri = $uri->parseRequestUri();
    	
    	return $this->_requestUri;
    }
    
    /**
     * Lấy ra tên area
     */
    public function getArea()
    {
    	return $this->_area;
    }
    
    /**
     * Gán tên area
     * @param string $area
     * @return XPHP_Router
     */
    public function setArea($area)
    {
    	$this->_area = $area;
    	return $this;
    }
    
    /**
     * Lấy ra controller
     */
	public function getController()
	{
		return $this->_controller;
	}
	
	/**
     * Gán tên controller
     * @param string $controller
     * @return XPHP_Router
     */
	public function setController($controller)
	{
		$this->_controller = $controller;
		return $this;
	}
	
	/**
	 * Lấy ra tên action
	 */
	public function getAction()
	{
		return $this->_action;
	}
	
	/**
     * Gán tên action
     * @param string $action
     * @return XPHP_Router
     */
	public function setAction($action)
	{
		$this->_action = $action;
		return $this;
	}
	
	/**
	 * Lấy ra các tham sô truyền vào
	 */
	public function getArgs()
	{
		return $this->_args;
	}
	
	/**
     * Gán tham số args
     * @param string $args
     *  @param bool $override có ghi đè hay không, mặc định là không ghi đè
     * @return XPHP_Router
     */	
	public function setArgs($args, $override = NULL)
	{
		//Nếu không ghi đè(Mặc định không ghi đè)
		if($override === NULL || !$override)
		{
			if(is_array($args))
				$result = array_merge((array)$this->_args, (array)$args);
			else 
				$this->_args[] = $args;
		}
		else
		{
			if(is_array($args))
				$this->_args = $args;
			else 
				$this->_args = array($args);
		}
	}
	
	/**
	 * Lấy ra thư mục chứa các area
	 */
	public function getAreaDir()
	{
		return $this->_areaDir;
	}
	
	/**
	 * Lấy ra thư mục application
	 */
	public function getApplicationDir()
	{
		return $this->_applicationDir;
	}
	
	/**
	 * Lấy ra tên thư mục chứa các controller
	 */
	public function getControllerDir()
	{
		return $this->_controllerDir;
	}
	
	/**
	 * Lấy ra đường dẫn của một area
	 * @param string $area Tên Area cần lấy đường dẫn
	 */
	public function getAreaPaths($area)
	{
		return $this->_areas[$area];
	}
	
	/**
	 * Lấy ra danh sách các area và đường dẫn của nó
	 */
	public function getListAreas()
	{
		return $this->_areas;
	}
	
	/**
	 * Lấy ra Controller Key
	 */
	public function getControllerKey()
	{
		return $this->_controllerKey;
	}
	/**
	 * Lấy ra Action Key
	 */
	public function getActionKey()
	{
		return $this->_actionKey;
	}
	/**
	 * Lấy ra Area Key
	 */
	public function getAreaKey()
	{
		return $this->_areaKey;
	}
	
	public function getInstant()
	{
		$router = new XPHP_Router();
		$router->_action = $this->_action;
		$router->_controller = $this->_controller;
		$router->_area = $this->_area;
		$router->_args = $this->_args;
		$router->_areas = $this->_areas;
		return $router;
	}
}